home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / pt20pc.zip / RE2.ASM < prev    next >
Assembly Source File  |  1991-02-04  |  7KB  |  292 lines

  1. ;
  2. ; al = input character
  3. ; di = nlist tail
  4. ; si = clist tail
  5. ; dx = clist head
  6. ;
  7. RE_TEXT    SEGMENT  WORD PUBLIC 'CODE'
  8.     assume    cs:RE_TEXT
  9.     assume    ds:RE_TEXT
  10.     assume    es:RE_TEXT
  11.     extrn    _reFast1:BYTE
  12.     extrn    _reFast2:BYTE
  13. ;
  14. ;    XTAG:re_scan
  15. ;    re_scan( char * beginBuffer, char * endBuffer, char *segBuffer,
  16. ;            char ** matchBegin, char ** matchEnd,
  17. ;            int * numberOfNewlines );
  18. ;
  19. ;    returns:
  20. ;        0 = NOT_FOUND -- RE was not found between beginBuffer
  21. ;                            and endBuffer
  22. ;        1 = FOUND -- RE was found between matchBegin and matchEnd
  23. ;        2 = PARTIAL_MATCH -- partial match at the end of the buffer
  24. ;                starting at matchBegin
  25. ;
  26.     public    _re_scan
  27. _re_scan PROC FAR
  28.     push    bp        ; save bp
  29.     mov    bp,sp        ; set up bp to access the arguments
  30. ;
  31.     mov    cs:dataSegment,ds    ; save ds
  32. ;
  33.     push    ds        ; save ds and es
  34.     push    es
  35.     push    si        ; save si and di
  36.     push    di
  37. ;
  38.     push    cs        ; have all the segment registers point to
  39.     pop    ds        ; the beginning of the code segment
  40.     push    cs
  41.     pop    es
  42. ;
  43.     mov    ax,[bp+6]    ; pick up and save the arguments
  44.     mov    cs:nextByteOffset,ax
  45.     mov    cs:firstByteOffset,ax
  46.     mov    ax,[bp+8]
  47.     mov    cs:lastByteOffset,ax
  48. ; move the segment into a position so GetNextChar can pick it up with a LDS
  49.     mov    ax,[bp+10]
  50.     mov    cs:nextByteSegment,ax
  51. ;
  52. init:
  53.     cld            ; set search direction to forward
  54.     lea    di,list1    ; initially list1=nlist and list2=clist
  55.     mov    nlistTop,di    ; but they are swapped after each character
  56.     lea    si,list2
  57.     mov    clistTop,si
  58.     mov    dx,si        ; dx = clist head
  59.     mov    al,0AH        ; "last char read" at beginning is a NL
  60.     jmp    myxchg
  61. ;
  62. ;
  63. finish:
  64.     ; count the number of lines in the scanned bytes
  65.     push    ax        ; save ax since we need to change al
  66.     mov    di,cs:firstByteOffset ; start the scan here
  67.     mov    cx,cs:nextByteOffset  ; compute the number of bytes to scan
  68.     mov    ds,cs:nextByteSegment
  69.     mov    es,cs:nextByteSegment
  70.     sub    cx,di        ; cx = the number of bytes
  71.     mov    al,0AH        ; 0AH = newline, ASCII line feed
  72.     xor    dx,dx        ; newline counter, start at 0 (of course)
  73. NLLoop:
  74.     repne scasb        ; scan to the next newline
  75.     jne    noMoreNLs    ; go to end of buffer w/o finding a newline
  76.     inc    dx        ; found another one, bump the counter
  77.     cmp    cx,0
  78.     jne    NLLoop        ; find any more
  79. noMoreNLs:
  80.     mov    ds,cs:dataSegment
  81.     mov    bx,[bp+16]    ; get address of int to put newline count in
  82.     mov    [bx],dx        ; store the computed newline count
  83.     ; end of newline counting
  84. ;
  85.     pop    ax        ; restore ax -- the return value
  86.     pop    di
  87.     pop    si
  88.     pop    es
  89.     pop    ds
  90.     pop    bp        ; restore bp
  91.     ret
  92. _re_scan ENDP    
  93. ;
  94.     public    _re_cnode
  95. _re_cnode:
  96.     pop    bx            ; get the return address
  97.     mov    [si],bx            ; save it in the clist
  98.     mov    cx,thisMatchBegin
  99.     mov    [si+2],cx
  100.     add    si,4            ; mov clist tail (si)
  101.     add    bx,3            ; generate bx+3 as an address
  102.     push    bx            ; push it so we can "JMP" to it
  103.     ret                ; with a RET.  We cannot use JMP 3[bx]
  104.                     ; directly since it will be indirect
  105. ;
  106.     public    _re_nnode
  107.     extrn    _addrJmpFound:WORD
  108. _re_nnode:
  109.     pop    bx            ; get the return address
  110.     cmp    bx,_addrJmpFound    ; did we find it?
  111.     je    _re_found
  112.     mov    [di],bx            ; save it in the nlist
  113.     mov    cx,thisMatchBegin
  114.     mov    [di+2],cx
  115.     add    di,4            ; mov nlist tail (di)
  116.                     ; then move to next clist item
  117. ;
  118.     public    _re_clist
  119. _re_clist:
  120.     cmp    dx,si
  121.     je    myxchg        ; head=tail => clist is empty
  122.     mov    bx,dx        ; move address into base register
  123.     mov    cx,[bx+2]
  124.     mov    thisMatchBegin,cx
  125.     add    dx,4        ; move to the next item
  126.     jmp    [bx]
  127. ;
  128.     public    _re_found
  129. _re_found:
  130.     mov    cx,thisMatchBegin
  131.     dec    cx        ; since it was taken from nextByteOffset
  132.                 ; and so is one to big
  133.     mov    ds,cs:dataSegment
  134.     mov    bx,[bp+12]
  135.     mov    [bx],cx        ; store begin address of found RE
  136.     mov    cx,cs:nextByteOffset
  137.     dec    cx        ; the RE ends here
  138.     mov    bx,[bp+14]
  139.     mov    [bx],cx        ; store end address of found RE
  140.     mov    ax,1        ; FOUND flag is returned in ax
  141.     jmp    finish
  142. ;
  143. ;
  144. myxchg:
  145.     cmp    di,nlistTop
  146.     jne    skipFastScan
  147. ;
  148. ; if this char is 0 then do not try fast searches, if it is not 0 then the
  149. ; first character of the RE is a single fixed character
  150. ;
  151.     cmp    _reFast1,0
  152.     je    skipFastScan
  153. ;
  154. ;  If there is no pending list of partial RE matches, then try to speed up
  155. ;  the search by scanning for the first character of the RE.  The 8086 string
  156. ;  search instructions are very fast for looking for a single character.
  157. ;
  158. ;  get the parameters for the string scan
  159.     push    ax    ; save last char read (in al)
  160.     mov    al,_reFast1
  161.     les    di,DWORD PTR nextByteOffset
  162.     mov    cx,lastByteOffset
  163.     cmp    cx,di
  164.     jbe    noScan
  165.     sub    cx,di
  166.     inc    cx    ; since lastByteOffset points to a valid byte
  167.     mov    dx,cx        ; save cx for the second scan
  168.  repne    scasb
  169.      jne    notFound1    ; distinguish: not found - found at last char
  170.     dec    di        ; adjust since repne scasb goes one too far
  171. notFound1:
  172.     mov    cx,dx        ; restore the count we saved
  173.     mov    dx,di        ; save the results of the first scasb in dx
  174.     mov    al,_reFast2    ; get the second fast scan character
  175.     jnz    doSecondScan    ; only look for chars not equal to '\0'
  176.     mov    di,lastByteOffset ; make sure this is not the lowest
  177.     jmp    notFound2
  178. doSecondScan:
  179.     mov    di,WORD PTR nextByteOffset
  180.  repne    scasb
  181.      jne    notFound2
  182.      dec    di
  183. notFound2:
  184.     ; use the one that came first (the lower one)
  185.     cmp    di,dx
  186.     jbe    useSecond
  187.     mov    di,dx
  188. useSecond:
  189.     mov    nextByteOffset,di
  190. noScan:
  191.     push    cs
  192.     pop    es        ; restore es (NECESSARY since we use DI)
  193.     mov    di,nlistTop    ; restore di
  194.     pop    ax        ; restore last char read (back into al)
  195. ;
  196. ;
  197. skipFastScan:
  198.     mov    si,di        ; set new clist tail
  199.     mov    di,clistTop    ; set new nlist tail
  200.     mov    bx,nlistTop    ; set up to exchange clist and nlist
  201.     mov    nlistTop,di    ; now do the reverse
  202.     mov    clistTop,bx    ; reversing is faster than moving the lists
  203.     mov    dx,bx        ; start adding at the top of the clist
  204. ;
  205. ; get the next character
  206. ;
  207.     lds    bx,DWORD PTR nextByteOffset
  208.     cmp    bx,cs:lastByteOffset
  209.     ja    endOfSpan    ; use unsigned comparison
  210.     mov    BYTE PTR cs:_re_sidechars,al ; save last char read
  211.     mov    al,[bx+1]    ; get char after the next one
  212.     mov    BYTE PTR cs:_re_sidechars+1,al ; save next char to read
  213.     mov    al,[bx]        ; get the next character (finally)
  214.     push    cs        ; restore DS to equal CS
  215.     pop    ds
  216.     inc    bx
  217.     cmp    bx,lastByteOffset ; are we at the end of the buffer?
  218.     jb    notAtEnd
  219.     mov    ah,0AH        ; if so, simulate a NL as the next char
  220.     mov    BYTE PTR _re_sidechars+1,ah
  221. notAtEnd:
  222.     mov    nextbyteOffset,bx
  223.     mov    thisMatchBegin,bx
  224.     jmp    _re_code
  225. ;
  226. endOfSpan:
  227. ;
  228.     mov    es,cs:nextByteSegment
  229.     cmp    dx,si
  230.     je    noClist
  231.     mov    bx,dx
  232.     mov    dx,cs:[bx+2]
  233. loop1:
  234.     add    bx,4
  235.     cmp    bx,si
  236.     je    endLoop
  237.     cmp    dx,cs:[bx+2]
  238.     jbe    loop1
  239.     mov    dx,cs:[bx+2]
  240.     jmp    loop1
  241. endLoop:
  242.     mov    ds,cs:dataSegment    ; restore ds
  243.     dec    dx        ; taken from nextByteOffset and so 1 too high
  244.     mov    bx,[bp+12]
  245.     mov    [bx],dx
  246.     mov    ax,2
  247.     jmp    over1
  248. noClist:
  249.     xor    ax,ax
  250. over1:
  251.     jmp    finish
  252. ;
  253.     even
  254.     public    _re_code
  255. _re_code:
  256.     db    1000 DUP (0)
  257. ;
  258.         even
  259. nlistTop    dw    0
  260. clistTop    dw    0
  261. firstByteOffset    dw    0
  262. ; These next words two must stay in this order since they are picked up with
  263. ; an LDS instruction that wants then in this order in two consecutive words
  264. nextByteOffset    dw    0
  265. nextByteSegment    dw    0
  266. dataSegment    dw    0
  267. ;
  268. ; Here we will keep the last character read and the next character to be read
  269. ;
  270.         public    _re_sidechars
  271. _re_sidechars    dw    0
  272. ;
  273. lastByteOffset    dw    0
  274. thisMatchBegin    dw    0
  275. ;
  276.         public    _re_wordtable
  277. _re_wordtable    db    0, 0, 0, 0, 0, 0, -1, 3
  278.         db    -2, -1, -1, 7, -2, -1, -1, 7
  279.         db    0, 0, 0, 0, 0, 0, 0, 0
  280.         db    0, 0, 0, 0, 0, 0, 0, 0
  281. ;
  282.     even
  283. list1:
  284.     db    400 DUP (0)
  285. ;
  286.     even
  287. list2:
  288.     db    400 DUP (0)
  289. ;
  290. RE_TEXT    ENDS
  291.     end
  292.